package com.command.center.pucms.pucmsgateway.service.impl;


import cn.hutool.crypto.digest.BCrypt;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.command.center.pucms.common.constant.Constant;
import com.command.center.pucms.common.enums.CodeEnum;
import com.command.center.pucms.common.exception.BusinessException;
import com.command.center.pucms.common.util.ComUtil;
import com.command.center.pucms.common.util.ServletUtils;
import com.command.center.pucms.common.util.SimpleJwtUtil;
import com.command.center.pucms.pucmsgateway.domain.User;
import com.command.center.pucms.pucmsgateway.mapper.UserMapper;
import com.command.center.pucms.pucmsgateway.service.IUserService;
import com.command.platform.mvc.service.impl.BaseServiceImpl;
import com.command.platform.redis.template.RedisRepository;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.AuthorizationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户服务实现类
 * </p>
 *
 * @author zlb
 * @since 2021-04-25
 */
@Service
public class UserServiceImpl extends BaseServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private RedisRepository redisRepository;

    @Autowired
    private UserMapper userMapper;



    @Override
    public Map<String, Object> checkUserNameAndPasswd(JSONObject requestJson) throws Exception{
        Map<String,Object> resultMap = Maps.newHashMapWithExpectedSize(1);
        String userName = requestJson.getString("userName");
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("name", userName);
        User user = userMapper.selectOne(queryWrapper);
        //验证用户密码和数据库中是否相同，数据库中密码采用密文形式
        if (ComUtil.isEmpty(user) || !BCrypt.checkpw(requestJson.getString("password"), user.getPassword())) {
            throw new BusinessException(CodeEnum.INVALID_USERNAME_PASSWORD.getMsg(),CodeEnum.INVALID_USERNAME_PASSWORD.getCode());
        }

        //获取用户信息
        User userBean = userMapper.getUserByUserName(user.getName());
        //用户拥有的角色集合
        List<String> roles = userBean.getRoles().stream().map(role -> role.getName()).collect(Collectors.toList());
        //所有权限
        List<String> functions = Lists.newArrayList();
        userBean.getRoles().stream().map(role ->
                role.getAuthorizes().stream().map(function -> function.getOpPerms()).collect(Collectors.toList())
        ).forEach(list-> list.stream().forEach(permission-> functions.add(permission)));
        //用户拥有的权限集合
        List<String> permissions = functions.stream().distinct().collect(Collectors.toList());

        //根据用户名+时间戳生成token
        Long currentTimeMillis = System.currentTimeMillis();
        String token= SimpleJwtUtil.sign(userName,currentTimeMillis);
        redisRepository.setExpire(userName,currentTimeMillis,Constant.REFRESH_EXPIRE_TIME);
        redisRepository.set(userName+Constant.SEPARATOR+Constant.ROLES, JSONUtil.toJsonStr(roles));
        redisRepository.set(userName+Constant.SEPARATOR+Constant.PERMISSIONS,JSONUtil.toJsonStr(permissions));

        resultMap.put(Constant.TOKEN_KEY,token);
        resultMap.put(Constant.ROLES,roles);
        resultMap.put(Constant.PERMISSIONS,permissions);

        return resultMap;
    }


    @Override
    public void logout() {
        HttpServletRequest request = ServletUtils.getRequest();
        String token = ServletUtils.getTokenFromRequest(request);
        try {
            if (SimpleJwtUtil.verify(token)){
                //清除shiro信息
                SecurityUtils.getSubject().logout();
            }
        } catch (Exception e) {
            throw new AuthorizationException("token不合法");
        }

    }


}
